package com.cskaoyan.gateway.controller.user;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.mall.commons.result.ResponseData;
import com.mall.commons.result.ResponseUtil;
import com.mall.commons.tool.utils.CookieUtil;
import com.mall.user.IKaptchaService;
import com.mall.user.ILoginService;
import com.mall.user.IRegisterService;
import com.mall.user.annotation.Anoymous;
import com.mall.user.constants.SysRetCodeConstants;
import com.mall.user.dto.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

/**
 * @description:
 * @autyor:caicaicai
 */
@Slf4j
@RestController//注册组件 + 返回为json字符串
@RequestMapping("/user")//拼接请求url
public class RegisterController {

    @Reference//远程调用微服务
    private IKaptchaService iKaptchaService;

    @Reference
    private IRegisterService iRegisterService;

    @Reference
    private ILoginService iLoginService;

    public static String USER_INFO_KEY="userInfo";

    public static String ACCESS_TOKEN="access_token";

    @PostMapping("/register")
    @Anoymous//设置方法对应的请求为匿名请求：注册请求，无需判断是否登录，直接放行
    public ResponseData register(@RequestBody Map<String, String> map, HttpServletRequest request){
        //请求参数为Json字符串，从map中取出请求参数
        String userName = map.get("userName");
        String userPwd = map.get("userPwd");
        String captcha = map.get("captcha");
        String email = map.get("email");

        //1.验证验证码
        KaptchaCodeResponse kaptchaCodeResponse = validateControllerKaptchaCode(request, captcha);
        String code = kaptchaCodeResponse.getCode();
        if(!code.equals(SysRetCodeConstants.SUCCESS.getCode())){
            //验证失败
            //响应数据的工具类：内部维护一个responseData, 失败setErrorMsg()
            log.error("注册接口 之 验证码验证失败");
           return new ResponseUtil<>().setErrorMsg(kaptchaCodeResponse.getMsg());
        }

        //2.去向用户表中插入记录
        UserRegisterRequest registerRequest = new UserRegisterRequest();
        registerRequest.setEmail(email);
        registerRequest.setUserName(userName);
        registerRequest.setUserPwd(userPwd);
        UserRegisterResponse registerResponse = iRegisterService.register(registerRequest);
        if(registerResponse.getCode().equals(SysRetCodeConstants.SUCCESS.getCode())){
            //插入记录成功
            //响应数据的工具类：内部维护一个responseData，构造方法默认成功true + 可单独设置data、code
            log.error("注册接口 之 注册成功");
            return new ResponseUtil<>().setData(null);
        }
        //响应数据的工具类：内部维护一个responseData, 失败setErrorMsg()
        log.error("注册接口 之 注册失败={}", registerResponse.getMsg());
        return new ResponseUtil<>().setErrorMsg(registerResponse.getMsg());
    }

    @PostMapping("/login")
    @Anoymous
    public ResponseData login(@RequestBody Map<String, String> map, HttpServletRequest request, HttpServletResponse httpServletResponse){
        //请求参数为Json字符串，从map中取出请求参数
        String userName = map.get("userName");
        String userPwd = map.get("userPwd");
        String captcha = map.get("captcha");

        //1.验证验证码
        KaptchaCodeResponse response = validateControllerKaptchaCode(request, captcha);
        String code = response.getCode();
        if(!code.equals(SysRetCodeConstants.SUCCESS.getCode())){
            //验证失败
            //响应数据的工具类：内部维护一个responseData, 失败setErrorMsg()
            log.error("验证码验证失败={}",response.getMsg());
            return new ResponseUtil<>().setErrorMsg(response.getMsg());
        }

        //2.验证用户名以及密码（查表：用户名唯一，得到密码是否相等）
        UserLoginRequest loginRequest = new UserLoginRequest();
        loginRequest.setUserName(userName);
        loginRequest.setPassword(userPwd);
        UserLoginResponse loginResponse = iLoginService.login(loginRequest);
        if(loginResponse.getCode().equals(SysRetCodeConstants.SUCCESS.getCode())){
            //token添加到cookie中
            Cookie cookie = new Cookie(ACCESS_TOKEN, loginResponse.getToken());
            //cookie有效范围："/"即所有请求；若不设置，在这则为"/user/*"
            cookie.setPath("/");
            CookieUtil.setCookie(httpServletResponse, cookie);
            log.info("登录成功，生成的token={},添加到cookie={}", loginResponse.getToken(), cookie.toString());
            log.info(loginResponse.toString());
            return new ResponseUtil<>().setData(loginResponse);
        }
        log.error("登录失败={}", loginResponse.getMsg());
        return new ResponseUtil<>().setErrorMsg(loginResponse.getMsg());
    }

    @GetMapping("/login")
    public ResponseData login(HttpServletRequest request){
        //拦截器取出token解密后存入request域中 --> 直接使用
        String userInfo = (String)request.getAttribute(USER_INFO_KEY);
        if("".equals(userInfo) || userInfo == null){
            //todo 未携带token(即没有登录状态的，处理是否合理？跳转到登录页面？）
            log.error("验证用户登录接口login() 之 request域中没有token");
            return new ResponseUtil<>().setErrorMsg(SysRetCodeConstants.TOKEN_VALID_FAILED.getMessage());
        }

        //json字符串还是字符串转化为map
        UserLoginValidResponse userLoginValidResponse = new UserLoginValidResponse();
        JSONObject object = JSON.parseObject(userInfo);
        Long uid = Long.parseLong(object.get("uid").toString());
        Object file = object.get("file");
        userLoginValidResponse.setUid(uid);
        if(file != null && !"".equals(file)){
            userLoginValidResponse.setFile(file.toString());
        }

        log.info("登录验证接口login() 之获得token中uid={}, file={}", uid, file);
        return new ResponseUtil<>().setData(userLoginValidResponse);
    }

    @GetMapping("/loginOut")
    public ResponseData loginOut(HttpServletResponse response, HttpServletRequest request){
        Cookie cookie = new Cookie(ACCESS_TOKEN, "");
        cookie.setPath("/");
        CookieUtil.setCookie(response, cookie);
        log.info("退出成功");
        return new ResponseUtil<>().setData(null);
    }

    @GetMapping("/verify")//?uid=xxx&username=xxx
    @Anoymous
    public ResponseData verify(UserVerifyRequest verifyRequest){
        UserVerifyResponse verifyResponse = iRegisterService.verify(verifyRequest);
        if(verifyResponse.getCode().equals(SysRetCodeConstants.SUCCESS.getCode())){
            log.error("用户激活vefify() 之 激活成功");
            return new ResponseUtil<>().setData(null);
        }
        //todo 返回 用户注册失败插入验证数据失败
        log.error("用户激活vefify() 之 激活失败");
        return new ResponseUtil<>().setErrorMsg(SysRetCodeConstants.USER_REGISTER_VERIFY_FAILED.getMessage());
    }

    /**
     * 验证验证码
     * （前端发送来的验证码和内存中的验证码/前一次请求获取验证码获得验证码是否一致）
     * @param request 前端发送来的http请求
     * @param captcha 请求参数中验证码
     * @return
     */
    private KaptchaCodeResponse validateControllerKaptchaCode(HttpServletRequest request, String captcha) {
        KaptchaCodeRequest kaptchaCodeRequest = new KaptchaCodeRequest();
        //uuid：通过cookie从前端传过来。
        // 前一个请求从验证码图片获取验证码，会生成对应的uuid，添加到cookie中；
        // 这次请求前端将这个uuid传给后端
        String uuid = CookieUtil.getCookieValue(request, "kaptcha_uuid");
        log.info("从cookie获取的uuid={}",uuid);
        kaptchaCodeRequest.setUuid(uuid);
        kaptchaCodeRequest.setCode(captcha);//验证码
        //iKaptchaService.validateKaptchaCode()验证图形验证码
        KaptchaCodeResponse response = iKaptchaService.validateKaptchaCode(kaptchaCodeRequest);
        return response;
    }
}
